package ai.restosuite.infrastructure.utils;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;

/**
 * http请求数据校验
 * @author yangzhen
 * @since 20250310
 */
public class OpenApiUtil{

    public static final String CONTENT_FIELD = "content";


    private String encodedKey = "17c9cb160a274a7592a765a3";

    private String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz93J4DTFmY36ZMYGBXRpIcKtGhuQIanqJY+7jNIWAVBO/iliqxn2u8POkZ/k7wjbxEYk22akSH8HCb5t4vF55jm2H26Epa0Ejd3/mIMGBP9BvzppZI6fpEZA9MfzpJCjhHmgCKImWThYltmrJj7QOOGY1sYUPUSsAn+BtTzpaFLVU4dZbzvjvXWCJ5dXbK4u/G71F0c8yBeetaVs6b3mxcc+0/6EuCivV9G/YiUIDclFeYsukQYZmHuYfGvVqsBOBYvn+JxtIQTwKXa+a+UIlDpPb8puOzp0eLl/EsIrgjzV4bztcZ3/BL9BdYBB+kYkFUWWebbfP8lrSHt6Ro82nQIDAQAB";

    public OpenApiUtil() {

    }

    public String decrypt(Map<String, Object> content) {
        try {
            Map<String, Object> result = DefaultOpenAPIUtil.discryption(content, this.publicKey, this.encodedKey);
            return result.get(CONTENT_FIELD).toString();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }


    /**
     * openapi工具类
     */
    private static class DefaultOpenAPIUtil {
        private static final String VERSION = "1.0";
        private static final String FORMAT = "JSON";
        private static final String SIGNTYPE = "RSA";
        private static final String SIGNTYPE_FIELD = "signType";
        private static final String SIGN_FIELD = "sign";
        private static final String FORMAT_FIELD = "format";
        private static final String TIMESTAMP_FIELD = "timestamp";
        private static final String VERSION_FIELD = "version";

        public static Map<String, Object> discryption(Map<String, Object> map, String publicKey, String encodedKey) {
            //解密
            String sign = (String) map.remove(SIGN_FIELD);
            if (RSAUtil.verify(RSAUtil.getSignatureContent(map), sign, publicKey)) {
                if(map.containsKey(CONTENT_FIELD)){
                    String plainContent = SecurityUtil.decrypt3DES(encodedKey, (String) map.get(CONTENT_FIELD));
                    Object value = plainContent;
                    //对象
                    if(StringUtils.startsWith(plainContent, "{") && StringUtils.endsWith(plainContent, "}")){
                        value = JSONObject.parseObject(plainContent);
                    }
                    //数组
                    else if(StringUtils.startsWith(plainContent, "[") && StringUtils.endsWith(plainContent, "]")){
                        value = JSONArray.parseArray(plainContent);
                    }
                    map.put(CONTENT_FIELD, value);
                }
                return map;
            } else {
                throw new RuntimeException("discryption error");
            }
        }
    }


    /**
     * 加密工具类
     */
    private static class SecurityUtil {
        private static final String ALGORITHM_3DES = "DESede";
        public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

        public static String decrypt3DES(String decryptPassword, String decryptString) {
            try {
                Cipher cipher = init3DES(decryptPassword, 2);
                byte[] deBytes = cipher.doFinal(Base64Util.decode2Byte(decryptString));
                return new String(deBytes, DEFAULT_CHARSET);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        private static Cipher init3DES(String decryptPassword, int cipherMode) throws Exception {
            SecretKey deskey = new SecretKeySpec(decryptPassword.getBytes(), ALGORITHM_3DES);
            Cipher cipher = Cipher.getInstance(ALGORITHM_3DES);
            cipher.init(cipherMode, deskey);
            return cipher;
        }
    }


    /**
     * RSA工具类
     */
    private static class RSAUtil {
        public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
        public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

        public static boolean verify(String content, String sign, String publicKey) {
            try {
                KeyFactory keyFactory = KeyFactory.getInstance(DefaultOpenAPIUtil.SIGNTYPE);
                byte[] encodedKey = Base64Util.decode2Byte(publicKey);
                PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
                Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
                signature.initVerify(pubKey);
                signature.update(content.getBytes(DEFAULT_CHARSET));
                boolean bverify = signature.verify(Base64Util.decode2Byte(sign));
                return bverify;
            } catch (Exception var8) {
                Exception e = var8;
                e.printStackTrace();
                return false;
            }
        }


        public static <T> String getSignatureContent(Map<String, T> params) {
            if (params == null) {
                return null;
            } else {
                StringBuffer content = new StringBuffer();
                List<String> keys = new ArrayList(params.keySet());
                Collections.sort(keys);

                for(int i = 0; i < keys.size(); ++i) {
                    String key = keys.get(i);
                    if (params.get(key) != null) {
                        String value = String.valueOf(params.get(key));
                        content.append((i == 0 ? "" : "&") + key + "=" + value);
                    }
                }

                return content.toString();
            }
        }

    }


    /**
     * Base64工具类
     */
    private static class Base64Util {
        public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

        public Base64Util() {
        }


        public static byte[] decode(byte[] bytes) {
            return org.apache.commons.codec.binary.Base64.decodeBase64(bytes);
        }

        public static byte[] decode2Byte(String targetString) {
            byte[] bytes = targetString.getBytes(DEFAULT_CHARSET);
            return org.apache.commons.codec.binary.Base64.decodeBase64(bytes);
        }

    }

}

